/**
 * 地图工具类
 * 提供地图初始化、图层管理等核心功能
 * @author rawcloud
 */
import * as Cesium from 'cesium'
import WmsWmtsUtils from './WmsWmtsUtils.js'
import ThreeDTilesUtils from './ThreeDTilesUtils'

class MapUtils {
  /**
   * 构造函数
   * @param {string} containerId - Cesium容器ID
   * @param {Object} options - 初始化选项
   */
  constructor(containerId, options = {}) {
    this.containerId = containerId
    this.options = options
    this.viewer = null
    this.tiandituToken = options.tiandituToken || '9fd6d5d2f4bebb703692deb3bc0a5da7'
    this.cesiumIonToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3ODZkMDQzOS03ZGJjLTQzZWUtYjlmYy04ZmM5Y2UwNzNhMmYiLCJpZCI6MjU5LCJpYXQiOjE2MzgyMDYwMDB9.cK1hsaFBgz0l2dG9Ry5vBFHWp-HF2lwjLC0tcK8Z8tY'
    this.resizeHandler = null
    this.currentBasemap = ''
    this.annotationLayer = null
    this.scgisLayer = null
    this.wmsWmtsUtils = null
    this.threeDTilesUtils = null
    this.customCesium = null
  }

  /**
   * 初始化Cesium Viewer
   * @returns {Promise<Cesium.Viewer>} Cesium Viewer实例
   */
  async initViewer() {
    try {
      const container = document.getElementById(this.containerId)
      if (!container) {
        throw new Error('Cesium container not found')
      }

      // 确保容器有正确的尺寸
      const containerStyle = window.getComputedStyle(container)
      const width = parseInt(containerStyle.width)
      const height = parseInt(containerStyle.height)

      if (width <= 0 || height <= 0) {
        // 如果尺寸不正确，强制设置尺寸
        container.style.width = '100%'
        container.style.height = '100vh'
        console.warn('Forced Cesium container size to 100% x 100vh')
      }

      // 初始化Cesium Viewer
    this.viewer = new Cesium.Viewer(this.containerId, {
        animation: false,
        baseLayerPicker: false,
        fullscreenButton: false,
        geocoder: false,
        homeButton: false,
        infoBox: false,
        sceneModePicker: false,
        selectionIndicator: false,
        timeline: false,
        navigationHelpButton: false,
        navigationInstructionsInitiallyVisible: false,
        // 设置哥伦布视图模式（3D）
        sceneMode: Cesium.SceneMode.SCENE3D,
        // 渲染配置 - 关闭请求渲染模式以提高绘制流畅度
        requestRenderMode: false, // 关闭请求渲染模式，确保实时更新
        maximumRenderTimeChange: 0.0, // 最小化渲染时间变化
        scene3DOnly: true, // 仅3D模式以提高性能
        imageryProvider: false, // 禁用默认影像提供者
        baseLayer: false, // 禁用默认底图
        ...this.options.viewerOptions
      })
this.customCesium = Cesium;
      // 隐藏logo信息
      if (this.viewer._cesiumWidget && this.viewer._cesiumWidget._creditContainer) {
        this.viewer._cesiumWidget._creditContainer.style.display = 'none'
      }

      // 设置渲染质量和性能平衡
      this.viewer.scene.globe.maximumScreenSpaceError = 2; // 较低的值提高细节质量

      // 启用抗锯齿以提高线条平滑度
      this.viewer.scene.fxaa = true;
      this.viewer.scene.postProcessStages.fxaa.enabled = true;

      // 优化性能
      this.viewer.scene.debugShowFramesPerSecond = false;
      this.viewer.scene.requestRenderMode = false;

      // 关闭深度测试，确保影像图层正确显示
      this.viewer.scene.globe.depthTestAgainstTerrain = false

      // 默认禁用地形
      this.viewer.terrainProvider = new Cesium.EllipsoidTerrainProvider()

      // 设置默认相机视角
      this.setDefaultCameraView()

      // 添加窗口大小变化的监听器
      this.addResizeHandler()

      // 初始化WMS/WMTS工具类
  this.wmsWmtsUtils = new WmsWmtsUtils(this.viewer)
    
    // 初始化3D Tiles工具
    this.threeDTilesUtils = new ThreeDTilesUtils(this.viewer)
    
  return this.viewer
    } catch (error) {
      console.error('Error initializing Cesium Viewer:', error)
      throw error
    }
  }

  /**
   * 设置默认相机视角
   */
  setDefaultCameraView() {
    if (!this.viewer) return

    // 设置2.5D模式（倾斜视角）
    this.viewer.scene.camera.setView({
      // 中国中心点坐标（北京）
      destination: Cesium.Cartesian3.fromDegrees(116.3974, 39.9093, 10000000),
      // 相机朝向：北偏东30度
      heading: Cesium.Math.toRadians(30.0),
      // 俯仰角：-45度（倾斜视角）
      pitch: Cesium.Math.toRadians(-45.0),
      // 滚动角：0度
      roll: 0.0
    })
  }

  /**
   * 添加窗口大小变化的监听器
   */
  addResizeHandler() {
    this.resizeHandler = () => {
      if (this.viewer && this.viewer.resize) {
        this.viewer.resize()
      }
    }
    window.addEventListener('resize', this.resizeHandler)
  }

  /**
   * 获取底图提供者配置
   * @returns {Object} 底图提供者对象
   */
  getBasemapProviders() {
    return {
      img: new Cesium.WebMapTileServiceImageryProvider({
        url: `https://t0.tianditu.gov.cn/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${this.tiandituToken}`,
        layer: 'img',
        style: 'default',
        format: 'tiles',
        tileMatrixSetID: 'w',
        maximumLevel: 18,
        credit: new Cesium.Credit('天地图影像')
      }),
      
      vec: new Cesium.WebMapTileServiceImageryProvider({
        url: `https://t0.tianditu.gov.cn/vec_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=vec&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${this.tiandituToken}`,
        layer: 'vec',
        style: 'default',
        format: 'tiles',
        tileMatrixSetID: 'w',
        maximumLevel: 18,
        credit: new Cesium.Credit('天地图矢量')
      }),
      
      ter: new Cesium.WebMapTileServiceImageryProvider({
        url: `https://t0.tianditu.gov.cn/ter_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=ter&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${this.tiandituToken}`,
        layer: 'ter',
        style: 'default',
        format: 'tiles',
        tileMatrixSetID: 'w',
        maximumLevel: 18,
        credit: new Cesium.Credit('天地图地形')
      })
    }
  }

  /**
   * 获取注记图层提供者
   * @returns {Cesium.WebMapTileServiceImageryProvider} 注记图层提供者
   */
  getAnnotationProvider() {
    return new Cesium.WebMapTileServiceImageryProvider({
      url: `https://t0.tianditu.gov.cn/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${this.tiandituToken}`,
      layer: 'cia',
      style: 'default',
      format: 'tiles',
      tileMatrixSetID: 'w',
      maximumLevel: 18,
      credit: new Cesium.Credit('天地图注记')
    })
  }

  /**
   * 创建SCGIS WMTS图层提供者
   * @returns {Cesium.WebMapTileServiceImageryProvider} SCGIS图层提供者
   */
  createScgisProvider() {
    return new Cesium.WebMapTileServiceImageryProvider({
      // 简化URL模板，使用Cesium的变量替换机制
      url: 'https://www.scgis.net/services/newtianditudom/WMTS?service=WMTS&version=1.0.0&request=GetTile&tilematrix={TileMatrix}&tilerow={TileRow}&tilecol={TileCol}&layer=defaultLayer&style=default&format=image/png&tk=eb270c0127fpuolun7b36f27a1ba556d',
      layer: '四川省影像地图服务',
      style: 'default',
      format: 'image/png',
      // 设置tileMatrixSetID为'c'，表示4326地理坐标系
      tileMatrixSetID: 'GetTileMatrix',
      projection: new Cesium.WebMercatorProjection(Cesium.Ellipsoid.WGS84),
      credit: new Cesium.Credit('SCGIS天地图'),
      // 瓦片矩阵集配置
      tileMatrixLabels: Array.from({length: 18}, (_, i) => (i + 2).toString()),
      maximumLevel: 18,
      minimumLevel: 2,
      tilingScheme: new Cesium.GeographicTilingScheme({
          numberOfLevelZeroTilesX: 4,
          numberOfLevelZeroTilesY: 2,
          ellipsoid: Cesium.Ellipsoid.WGS84,
          origin: Cesium.Cartesian3.fromDegrees(90, -180),
          rectangle: Cesium.Rectangle.fromDegrees(-180, -90, 180, 90)
      }),
    })
  }

  /**
   * 切换底图
   * @param {string} type - 底图类型: 'img', 'vec', 'ter'
   * @param {boolean} showAnnotation - 是否显示注记图层
   * @param {boolean} showScgisLayer - 是否显示SCGIS图层
   */
  switchBasemap(type, showAnnotation = true, showScgisLayer = false) {
    if (!this.viewer) return
    if (this.currentBasemap === type) return
    
    this.currentBasemap = type
    this.viewer.imageryLayers.removeAll()
    
    // 添加底图
    const basemapProviders = this.getBasemapProviders()
    const basemapLayer = new Cesium.ImageryLayer(basemapProviders[type])
    this.viewer.imageryLayers.add(basemapLayer)
    
    // 如果注记图层开启，添加到顶部
    if (showAnnotation) {
      this.toggleAnnotationLayer(true)
    }
    
    // 如果SCGIS图层开启，添加到顶部，使用统一的配置
    if (showScgisLayer) {
      this.toggleScgisLayer(true)
    }
  }

  /**
   * 切换注记图层显示/隐藏
   * @param {boolean} show - 是否显示注记图层
   */
  toggleAnnotationLayer(show) {
    if (!this.viewer) return
    
    if (show) {
      // 创建注记图层
      const annotationProvider = this.getAnnotationProvider()
      this.annotationLayer = new Cesium.ImageryLayer(annotationProvider, {
        zIndex: 2 // 确保注记图层在最顶层
      })
      this.viewer.imageryLayers.add(this.annotationLayer)
    } else {
      // 移除注记图层
      if (this.annotationLayer) {
        this.viewer.imageryLayers.remove(this.annotationLayer)
        this.annotationLayer = null
      }
    }
  }

  /**
   * 切换SCGIS图层显示/隐藏
   * @param {boolean} show - 是否显示SCGIS图层
   * @param {number} alpha - 透明度 (0-1)
   * @param {number} zIndex - 层级索引
   * @returns {boolean} 操作是否成功
   */
  toggleScgisLayer(show, alpha = 1, zIndex = 0) {
    if (!this.viewer) return false
    
    try {
      if (show) {
        // 创建并添加SCGIS图层
        const scgisProvider = this.createScgisProvider()
        this.scgisLayer = new Cesium.ImageryLayer(scgisProvider, {
          alpha: alpha,
          zIndex: zIndex
        })
        
        // 添加图层
        this.viewer.imageryLayers.add(this.scgisLayer)
        return true
      } else {
        // 移除SCGIS图层
        if (this.scgisLayer) {
          this.viewer.imageryLayers.remove(this.scgisLayer)
          this.scgisLayer = null
          return true
        }
      }
    } catch (error) {
      console.error('添加SCGIS图层时出错:', error)
    }
    return false
  }

  /**
   * 切换地形显示/隐藏
   * @param {boolean} enable - 是否启用地形
   * @returns {Promise<boolean>} 操作是否成功
   */
  async toggleTerrain(enable) {
    if (!this.viewer) return false
    
    try {
      if (enable) {
        // 启用地形并添加加载状态监测
        await this.loadTerrain()
        // 地形启用后，通知 threeDTilesUtils 重新应用所有已标记为贴地的 tileset
        try {
          if (this.threeDTilesUtils && typeof this.threeDTilesUtils.reapplyAllClamps === 'function') {
            this.threeDTilesUtils.reapplyAllClamps()
          }
        } catch (e) {
          console.warn('reapplyAllClamps 调用失败:', e)
        }
        return true
      } else {
        // 禁用地形
        this.disableTerrain()
        return true
      }
    } catch (error) {
      console.error('地形切换错误:', error)
      this.disableTerrain()
      return false
    }
  }

  /**
   * 加载地形数据
   */
  async loadTerrain() {
    try {
      // 设置 Cesium Ion token（用于 createWorldTerrainAsync）
      if (this.cesiumIonToken) {
        Cesium.Ion.defaultAccessToken = this.cesiumIonToken
      }
      // 优先使用 Cesium 提供的 World Terrain（兼容 quantized-mesh）
      try {
        const terrain = await Cesium.CesiumTerrainProvider.fromUrl(
          '//data.mars3d.cn/terrain',
          {requestWaterMask: true,
          requestVertexNormals: true
        })
        this.viewer.terrainProvider = terrain
        console.log('已启用 Cesium World Terrain')
      } catch (errWorld) {
        console.warn('加载 Cesium World Terrain 失败，尝试使用备用 provider：', errWorld)

        // 试图使用天地图 QuantizedMesh 风格的服务（注意：大多数天地图 REST 并非 quantized-mesh，可能不兼容）
        const tiandituUrl = `https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer`
        try {
          const terrainProvider = new Cesium.ArcGISTiledElevationTerrainProvider({
            url: tiandituUrl,
            requestWaterMask: true,
            requestVertexNormals: true
          })
          if (terrainProvider.readyPromise) {
            await terrainProvider.readyPromise
          }
          // 简单检测 provider 是否支持 requestTileGeometry
          if (typeof terrainProvider.requestTileGeometry !== 'function') {
            console.warn('检测到自定义 terrainProvider 可能不支持 quantized-mesh API，回退为椭球体')
            throw new Error('terrainProvider 不支持 requestTileGeometry')
          }
          this.viewer.terrainProvider = terrainProvider
          console.log('已启用自定义 CesiumTerrainProvider（天地图）')
        } catch (errTianditu) {
          console.error('备用地形 provider 启用失败，使用椭球体作为回退：', errTianditu)
          this.viewer.terrainProvider = new Cesium.EllipsoidTerrainProvider()
          // 继续但抛出以便上层知道发生了问题
          throw errTianditu
        }
      }

      // 渲染建议配置：提高细节质量并启用深度测试以确保地形与图层正确遮挡
      this.viewer.scene.globe.maximumScreenSpaceError = 1.5
      this.viewer.scene.globe.depthTestAgainstTerrain = true

      // 保留并配置垂直夸张，便于地形视觉调整
      this.viewer.scene.verticalExaggeration = 2
      this.viewer.scene.verticalExaggerationRelativeHeight = 0.1
    } catch (err) {
      console.log('地形加载失败:', err)
      throw err
    }
  }

  /**
   * 禁用地形
   */
  disableTerrain() {
    if (!this.viewer) return
    
    this.viewer.terrainProvider = new Cesium.EllipsoidTerrainProvider();
    this.viewer.scene.verticalExaggeration = 0
    // 垂直地形夸张相对高度，默认值0
    this.viewer.scene.verticalExaggerationRelativeHeight = 0
  }

  /**
   * 加载3D Tiles数据集
   * @param {string} url - 3D Tiles数据集的URL路径（通常指向tileset.json）
   * @param {Object} options - 加载选项
   * @returns {Promise<string>} 加载的数据集ID
   */
  async load3DTileset(url, options = {}) {
    if (!this.threeDTilesUtils) {
      throw new Error('3D Tiles工具未初始化')
    }
    
    return this.threeDTilesUtils.loadTileset(url, options)
  }

  /**
   * 设置3D Tiles数据集的样式
   * @param {string} tilesetId - 数据集ID
   * @param {Object|string} style - 样式配置对象或样式表达式
   * @returns {boolean} 操作是否成功
   */
  set3DTilesetStyle(tilesetId, style) {
    if (!this.threeDTilesUtils) {
      console.error('3D Tiles工具未初始化')
      return false
    }
    
    return this.threeDTilesUtils.setTilesetStyle(tilesetId, style)
  }

  /**
   * 定位到指定的3D Tiles数据集
   * @param {string} tilesetId - 数据集ID
   * @param {Object} options - 定位选项
   * @returns {boolean} 操作是否成功
   */
  flyTo3DTileset(tilesetId, options = {}) {
    if (!this.threeDTilesUtils) {
      console.error('3D Tiles工具未初始化')
      return false
    }
    
    return this.threeDTilesUtils.flyToTileset(tilesetId, options)
  }

  /**
   * 显示/隐藏3D Tiles数据集
   * @param {string} tilesetId - 数据集ID
   * @param {boolean} show - 是否显示
   * @returns {boolean} 操作是否成功
   */
  show3DTileset(tilesetId, show) {
    if (!this.threeDTilesUtils) {
      console.error('3D Tiles工具未初始化')
      return false
    }
    
    return this.threeDTilesUtils.showTileset(tilesetId, show)
  }

  /**
   * 移除3D Tiles数据集
   * @param {string} tilesetId - 数据集ID
   * @returns {boolean} 操作是否成功
   */
  remove3DTileset(tilesetId) {
    if (!this.threeDTilesUtils) {
      console.error('3D Tiles工具未初始化')
      return false
    }
    
    return this.threeDTilesUtils.removeTileset(tilesetId)
  }

  /**
   * 获取所有已加载的3D Tiles数据集信息
   * @returns {Array} 数据集信息数组
   */
  getLoaded3DTilesets() {
    if (!this.threeDTilesUtils) {
      console.error('3D Tiles工具未初始化')
      return []
    }
    
    return this.threeDTilesUtils.getLoadedTilesets()
  }

  /**
   * 设置3D Tiles数据集的渲染质量
   * @param {string} tilesetId - 数据集ID
   * @param {number} maximumScreenSpaceError - 最大屏幕空间误差（值越小越精细）
   * @returns {boolean} 操作是否成功
   */
  set3DTilesetRenderQuality(tilesetId, maximumScreenSpaceError) {
    if (!this.threeDTilesUtils) {
      console.error('3D Tiles工具未初始化')
      return false
    }
    
    return this.threeDTilesUtils.setRenderQuality(tilesetId, maximumScreenSpaceError)
  }

  /**
   * 从URL加载WMTS服务
   * @param {string} xmlUrl - WMTS服务的XML描述文件URL
   * @param {Object} layerOptions - 图层选项（透明度、zIndex等）
   * @returns {Promise<Array>} 加载的图层ID数组
   */
  async loadWMTSFromUrl(xmlUrl, layerOptions = {}) {
    if (!this.wmsWmtsUtils) {
      throw new Error('WMS/WMTS工具类未初始化')
    }
    
    return this.wmsWmtsUtils.loadWMTSFromUrl(xmlUrl, layerOptions)
  }

  /**
   * 添加WMTS图层
   * @param {Object} params - WMTS服务参数
   * @param {Object} layerOptions - 图层选项
   * @returns {string} 图层ID
   */
  async addWMTSLayer(params, layerOptions = {}) {
    if (!this.wmsWmtsUtils) {
      throw new Error('WMS/WMTS工具类未初始化')
    }
    
    return this.wmsWmtsUtils.addWMTSLayer(params, layerOptions)
  }

  /**
   * 添加WMS图层
   * @param {Object} params - WMS服务参数
   * @param {Object} layerOptions - 图层选项
   * @returns {string} 图层ID
   */
  addWMSLayer(params, layerOptions = {}) {
    if (!this.wmsWmtsUtils) {
      throw new Error('WMS/WMTS工具类未初始化')
    }
    
    return this.wmsWmtsUtils.addWMSLayer(params, layerOptions)
  }

  /**
   * 移除图层
   * @param {string} layerId - 图层ID
   * @returns {boolean} 是否成功移除
   */
  removeLayer(layerId) {
    if (!this.wmsWmtsUtils) {
      return false
    }
    
    return this.wmsWmtsUtils.removeLayer(layerId)
  }

  /**
   * 显示/隐藏图层
   * @param {string} layerId - 图层ID
   * @param {boolean} show - 是否显示
   * @returns {boolean} 操作是否成功
   */
  showLayer(layerId, show) {
    if (!this.wmsWmtsUtils) {
      return false
    }
    
    return this.wmsWmtsUtils.showLayer(layerId, show)
  }

  /**
   * 更新图层透明度
   * @param {string} layerId - 图层ID
   * @param {number} alpha - 透明度 (0-1)
   * @returns {boolean} 操作是否成功
   */
  setLayerOpacity(layerId, alpha) {
    if (!this.wmsWmtsUtils) {
      return false
    }
    
    return this.wmsWmtsUtils.setLayerOpacity(layerId, alpha)
  }

  /**
   * 获取所有已加载的图层信息
   * @returns {Array} 图层信息数组
   */
  getLoadedLayers() {
    if (!this.wmsWmtsUtils) {
      return []
    }
    
    return this.wmsWmtsUtils.getLoadedLayers()
  }

  /**
   * 清理资源
   */
  destroy() {
    // 移除窗口大小变化监听器
    if (this.resizeHandler) {
      window.removeEventListener('resize', this.resizeHandler)
      this.resizeHandler = null
    }
    
    // 销毁WMS/WMTS工具类
    if (this.wmsWmtsUtils) {
      this.wmsWmtsUtils.destroy()
      this.wmsWmtsUtils = null
    }
    
    // 清理3D Tiles工具
    if (this.threeDTilesUtils) {
      this.threeDTilesUtils.destroy()
      this.threeDTilesUtils = null
    }
    
    // 销毁Cesium Viewer实例
    if (this.viewer) {
      this.viewer.destroy()
      this.viewer = null
    }
    
    // 重置状态
    this.currentBasemap = ''
    this.annotationLayer = null
    this.scgisLayer = null
  }
  
  /**
   * 创建基于高度的3D Tiles颜色样式
   * @param {Array} conditions - 颜色条件数组，格式：[[height, color], ...]
   * @param {string} defaultColor - 默认颜色（当不满足任何条件时使用）
   * @returns {Object} Cesium3DTileStyle配置对象
   */
  createHeightBased3DTilesStyle(conditions = [], defaultColor = 'color(\'blue\')') {
    if (!this.threeDTilesUtils) {
      console.error('3D Tiles工具未初始化')
      return {}
    }
    
    return this.threeDTilesUtils.createHeightBasedStyle(conditions, defaultColor)
  }

  /**
   * 设置3D Tiles数据集的贴地属性
   * @param {string} tilesetId - 数据集ID
   * @param {boolean} clampToGround - 是否贴地
   * @param {number} heightOffset - 高度偏移量（米）
   * @returns {boolean} 操作是否成功
   */
  set3DTilesetClampToGround(tilesetId, clampToGround, heightOffset = 0) {
    if (!this.threeDTilesUtils) {
      console.error('3D Tiles工具未初始化')
      return false
    }
    
    return this.threeDTilesUtils.setTilesetClampToGround(tilesetId, clampToGround, heightOffset)
  }
}

export default MapUtils